-- BlackMarketM
-- Created by zouyb
-- 黑市商人模块

module("BlackMarketM", package.seeall);

-- 配置
local config = {};

-- 所有的商品信息
local goodsTable = {};

-- 商店信息
local shopInfo = {};

-- 载入配置表
local _init = false;
local loadCsv = function()
    if _init then return end
    _init = true;

    -- 转换下信息表
    config = {};
    goodsTable = {};

    local black_market_rule_CSV = get_black_market_rule_CSV();
    for i = 1, #black_market_rule_CSV do
        config[black_market_rule_CSV[i].id] = parsePos(black_market_rule_CSV[i]);
    end

    -- 转换下shop_goods配置表
    local black_market_goods_CSV = get_black_market_goods_CSV();
    for i = 1, #black_market_goods_CSV do
        -- 解析出商品信息
        goodsTable[black_market_goods_CSV[i].id] = parseGoods(black_market_goods_CSV[i])
    end

    black_market_goods_CSV = {};
end

-- 初始化
function init()
    shopInfo = {};
    loadCsv();
end

-- 解析位置信息
function parsePos(info)
    local str = info.pos;

    if not string.startWith(str, "(") or not string.endWith(str, ")") then
        error(string.format("(%s)配置格式错误!", tostring(str)));
        return info;
    end

    local arr = string.explode(string.sub(str, 2, -2), ",");
    if #arr ~= 2 then
        error(string.format("(%s)配置格式错误!", tostring(str)));
        return info;
    end

    local offset = info.effect_offset;

    if not string.startWith(offset, "(") or not string.endWith(offset, ")") then
        error(string.format("(%s)配置格式错误!", tostring(offset)));
        return info;
    end

    local offsetArr = string.explode(string.sub(offset, 2, -2), ",");
    if #offsetArr ~= 2 then
        error(string.format("(%s)配置格式错误!", tostring(offset)));
        return info;
    end

    info["pos"]          = cc.p(tonumber(arr[1]), tonumber(arr[2]));
    info["effectOffset"] = cc.p(tonumber(offsetArr[1]), tonumber(offsetArr[2]));

    return info;
end

-- 解析商品数据
function parseGoods(info)
    -- 商品
    local arr = string.explode(string.sub(info.goods, 3, -2), ",")
    info.goods = { 1, tonumber(arr[1]), tonumber(arr[2]), }

    -- 价格
    local ret = {}
    local prices = string.explode(info.price, "|")
    for index, price in pairs(prices) do
        -- 每个价格都是price1 + price2 + .. 这个格式的
        ret[index] = {}
        local desc = string.explode(price, "+")
        for i = 1, #desc do
            arr = string.explode(string.sub(desc[i], 3, -2), ",");
            if string.startWith(desc[i], "1(") then
                -- 物品
                ret[index][i] = { 1, tonumber(arr[1]), tonumber(arr[2]), }
            else
                -- 属性
                ret[index][i] = { 2, arr[1], tonumber(arr[2]), }
            end
        end
    end

    info.price = ret;

    return info
end

-- 获取商品
function queryGoodsInfo(goodsId)
    -- 返回商品
    return goodsTable[goodsId].goods
end

-- 获取商品类别
function queryClassify(goodsId)
    -- 返回商品
    return goodsTable[goodsId].classify
end

-- 检索商品价格
function queryPrice(goodsId, index)
    local m = goodsTable[goodsId].price

    if not m or #m <= index then
        return nil
    end

    return m[index + 1][1]
end

-- 检索
function queryRule(id, path)
    local m = config[id];

    if not m or not path then
        return m;
    end

    return m[path];
end

-- 是否是打折商品
-- @goodsIndex 商品位置（注：这里的位置和服务器一致，都是从0开始的）
function isDiscountGoods(goodsIndex)
    if not shopInfo then
        return false;
    end

    local discount_index = shopInfo.discount_index;
    if type(discount_index) ~= "table" then
        return false;
    end

    return table.indexOf(discount_index, goodsIndex) ~= -1;
end

-- 计算商品价格
-- @goodsIndex 商品位置（注：这里的位置和服务器一致，都是从0开始的）
function calcGoodsPrice(goodsIndex)
    if not shopInfo then
        trace("BlackMarketM", "黑市商店数据不存在。");
        return nil;
    end

    local goodsInfo = shopInfo.goods[goodsIndex];
    if not goodsInfo then
        -- 商品不存在
        trace("BlackMarketM", "位置(%d)的商品不存在。", goodsIndex);
        return nil;
    end

    local priceIndex = goodsInfo.price;
    local arr;
    if goodsInfo.goods_type == "honor_scrap" then
        arr = parseGoodsPrice(priceIndex);
    else
        local goodsId = goodsInfo.goods_id;
        arr = queryPrice(goodsId, priceIndex);
    end

    if isDiscountGoods(goodsIndex) then
        -- 折扣商品
        local discountVal = FormulaM.invoke("CALC_BLACK_MARKET_DISCOUNT");
        local priceVal = math.max(1, math.modf(arr[3] * discountVal / 100));
        return { arr[1], arr[2], priceVal, };
    end

    return arr;
end

-- 判断能否购买物品，只判断价格
function canBuyGoods(goodsIndex)
    local info = shopInfo;

    -- 没有该商店信息
    local goodsInfo = info.goods[goodsIndex];
    if not info or not goodsInfo then
        return false
    end

    -- 如果已经买过了
    if goodsInfo.sold_out then
        return "sold_out"   -- 商品已售完
    end

    local priceIndex = goodsInfo.price;
    local goodsId = goodsInfo.goods_id;
    local arr = calcGoodsPrice(goodsIndex);
    if not arr then
        trace("BlackMarketM", "获取位置(%d)的商品价格失败了。", goodsIndex);
        return false;
    end

    local ok = true;

    if arr[1] == 1 then
        -- 物品
        ok = ItemM.getAmount(ME.user, arr[2]) >= arr[3]
        if not ok then
            return "item_lack"   -- 物品数量不足
        end
    elseif arr[1] == 2 then
        -- 属性
        ok = ME.user.dbase:query(arr[2], 0) >= arr[3]
        if not ok then
            return arr[2] .. "_lack"  -- 属性数量不足
        end
    else
        return false
    end

    return ok
end

-- 判断能否刷新商品
function canRefreshGoods()
    local ok = true;
    local cost = FormulaM.invoke("CALC_BLACK_MARKET_REFRESH_COST", ME.user, getShopRefreshCount());
    for _, arr in pairs(cost) do
        if arr[1] == 2 then
            ok = ME.user.dbase:query(arr[2], 0) >= arr[3];
        end

        if true ~= ok then
            return "cost_lack";
        end
    end

    return ok;
end

-- 更新商店信息
function updateInfo(info)
    shopInfo = info;

    EventMgr.fire(event.BLACKMARKET_INFO, info);
end

-- 获取商店信息
function getShopInfo()
    return shopInfo;
end

-- 是否存在商店
function isExist()
    if shopInfo ~= nil and shopInfo.id > 0 then
        return true;
    end

    return true;
end

-- 获取商店ID
function getShopId()
    if shopInfo ~= nil then
        return shopInfo.id;
    end

    return 0;
end

-- 获取商店手动刷新次数
function getShopRefreshCount()
    if shopInfo ~= nil and shopInfo.refresh_count ~= nil then
        return shopInfo.refresh_count;
    end

    return 0;
end

-- 获取商店自动刷新时间
function getShopAutoRefreshTime()
    if shopInfo ~= nil and shopInfo.auto_refresh_time ~= nil then
        return shopInfo.auto_refresh_time;
    end

    return 0;
end

-- 商店刷新剩余时间
function getShopAutoRefreshLeftTime()
    local serverTime = TimeM.getServerTime();
    if shopInfo ~= nil and shopInfo.auto_refresh_time ~= nil then
        return shopInfo.auto_refresh_time - serverTime;
    end

    return 0;
end

-- 获取商店商品
function getAllGoods()
    local list = {};
    if shopInfo == nil or shopInfo.goods == nil then
        return {};
    end

    -- 按照位置升序
    local indexList = table.keys(shopInfo.goods);
    table.sort(indexList);

    for _, index in pairs(indexList) do
        local info = shopInfo.goods[index];
        table.insert(list, info);
    end

    return list;
end

-- 根据索引获得商店出售物品信息
function getGoodInfoInShop(goodsIndex)
    if shopInfo == nil then
        return nil;
    end

    return shopInfo.goods[goodsIndex];
end

-- 获得商品价格
function parseGoodsPrice(price)
    local priceArray = price[1];
    return priceArray;
end

-- 获得商品信息
function queryCurShopGoods(goodsId)
    if shopInfo == nil then
        return nil;
    end

    local goodsInfo = getAllGoods();

    for k, v in pairs(goodsInfo) do
        if v.goods_id == goodsId then
            if v.goods_type == "honor_scrap" then
                return v.goods;
            else
                return queryGoodsInfo(goodsId)
            end
        end
    end
end

-- 客户端提前购买
function buyGoods(goodsIndex)
    local info = shopInfo;

    -- 没有该商店信息
    local goodsInfo = info.goods[goodsIndex];
    if not info or not goodsInfo then
        return false
    end

    -- 如果已经买过了
    if goodsInfo.sold_out then
        return "sold_out"   -- 商品已售完
    end

    local priceIndex = goodsInfo.price;
    local goodsId = goodsInfo.goods_id;
    local arr = calcGoodsPrice(goodsIndex);

    -- 记录下，失败之后需要还原回去
    ME.user.black_buy_temp = ME.user.black_buy_temp or {};
    table.insert(ME.user.black_buy_temp, arr);

    if arr[1] == 1 then
        -- 物品
        ItemM.costAmount(ME.user, arr[2], arr[3]);
    elseif arr[1] == 2 then
        -- 属性
        ME.user:costAttrib(arr[2], arr[3]);
    else
        return false
    end

    return true;
end

-- 购买结果
function buyGoodsResult(goodsId, result)
    local temp = ME.user.black_buy_temp or {};
    local arr = temp[1];

    table.remove(temp, 1);

    -- 如果没有购买成功
    if 1 ~= result then
        -- 需要把消耗补充回来，按顺序来就行了
        local temp = ME.user.black_buy_temp;
        if arr and sizeof(arr) == 3 then
            BonusM.doBonus(arr);
        end
        return;
    end

    EventMgr.fire(event.BLACKMARKET_BUY_GOODS, { ["goodsId"] = goodsId, ["result"] = result });
end
